package cn.b.sky.flowable.service.impl;

import cn.b.sky.flowable.dao.SkyServiceDao;
import cn.b.sky.flowable.enums.ServiceResponseCode;
import cn.b.sky.flowable.model.SkyService;
import cn.b.sky.flowable.model.ServiceTest;
import cn.b.sky.flowable.model.condition.SkyServiceCondition;
import cn.b.sky.flowable.service.SkyServiceService;
import cn.b.sky.common.constants.SystemConstant;
import cn.b.sky.common.utils.DateUtils;
import cn.b.sky.common.utils.SpringBeanUtil;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.List;

@Service("skyService")
public class SkyServiceImpl implements SkyServiceService {

  /**
   * 记录日志
   */
  private static final Logger LOG = LoggerFactory.getLogger(SkyServiceImpl.class);

  @Autowired
  private SkyServiceDao skyServiceDao;

  @Override
  public List<SkyService> getService(SkyServiceCondition condition) {

    return skyServiceDao.getServiceByCondition(condition);
  }

  @Override
  public int getServiceCount(SkyServiceCondition condition) {

    return skyServiceDao.getServiceCountByCondition(condition);
  }

  @Override
  public SkyService getSkyServiceById(Integer id) {
    if (id == null) {
      return null;
    }
    return skyServiceDao.getSkyServiceById(id);
  }

  @Override
  public void saveSkyService(SkyService service) {
    if (service != null) {
      skyServiceDao.insertSkyService(service);
    }
  }

  @Override
  public void modifySkyService(SkyService service) {
    if (service != null && service.getId() != null) {
      skyServiceDao.updateSkyService(service);
    }
  }

  @Override
  public SkyService getSkyServiceAndProcessByServiceId(Integer id) {
    if (id == null) {
      return null;
    }

    return skyServiceDao.getSkyServiceAndProcessByServiceId(id);
  }

  @Override
  public ServiceTest runImeServie(SkyService service) {
    ServiceTest serviceTest = new ServiceTest();
    if (service == null || service.getId() == null) {
      serviceTest.setResultStatus(ServiceResponseCode.ERROR.getValue());
      serviceTest.setReturnVal("执行出错,没有选择需要测试的服务！");
      return serviceTest;
    }
    String serviceCode = service.getServiceCode();
    if (!StringUtils.isBlank(serviceCode)) {
      try {
        this.execuService(serviceCode, service.getInParam(), serviceTest);
      } catch (NoSuchMethodException e) {
        LOG.error("{}", e);
        serviceTest.setResultStatus(ServiceResponseCode.ERROR.getValue());
        serviceTest.setReturnVal("执行出错,没有相应的服务或方法！" + e.getMessage());
      } catch (IllegalAccessException e) {
        LOG.error("{}", e);
        serviceTest.setResultStatus(ServiceResponseCode.ERROR.getValue());
        serviceTest.setReturnVal("执行出错,执行的方法参数有误！" + e.getMessage());
      } catch (InvocationTargetException e) {
        LOG.error("{}", e);
        serviceTest.setResultStatus(ServiceResponseCode.ERROR.getValue());
        serviceTest.setReturnVal("执行出错,执行服务方法时出错！" + e.getMessage());
      } catch (Exception e) {
        LOG.error("{}", e);
        serviceTest.setResultStatus(ServiceResponseCode.ERROR.getValue());
        serviceTest.setReturnVal("执行出错,执行服务方法时出错！" + e.getMessage());
      }

    }
    // 远程访问调用测试后续开发
    if (!StringUtils.isBlank(service.getUrl())) {
       //do something
    }
    return serviceTest;
  }

  private void execuService(String serviceCode, String inParam, ServiceTest serviceTest) throws NoSuchMethodException,
      IllegalAccessException, InvocationTargetException {
    if (serviceCode.indexOf(SystemConstant.SERVICECODE_SPLIT) != -1) {
      //.原字符转义
      String[] clazz = serviceCode.split("\\" + SystemConstant.SERVICECODE_SPLIT);
      Object service = SpringBeanUtil.getBean(clazz[0]);
      Method method = service.getClass().getDeclaredMethod(clazz[1], String.class);
      Date begin = DateUtils.getDateUtils().getCurrentDate();
      String returnVal = (String) method.invoke(service, inParam);
      Date end = DateUtils.getDateUtils().getCurrentDate();
      serviceTest.setResultStatus(ServiceResponseCode.OK.getValue());
      serviceTest.setReturnVal(returnVal);
      serviceTest.setBeginTime(DateUtils.getDateUtils().getDateStr(begin));
      serviceTest.setEndTime(DateUtils.getDateUtils().getDateStr(end));
      serviceTest.setTimes(DateUtils.getDateUtils().getHSMStrByTwoDate(begin, end));
    }
  }

  @Override
  public String searchServiceByJson(String condition) {
    if (StringUtils.isBlank(condition)) {
      return null;
    }
    SkyServiceCondition con = JSONObject.parseObject(condition, SkyServiceCondition.class);
    return JSONObject.toJSONString(skyServiceDao.getServiceByCondition(con));
  }

  @Override
  public List<SkyService> searchServiceByModelId(String modelId) {
    if (StringUtils.isBlank(modelId)) {
      return null;
    }
    return skyServiceDao.getServiceByModelId(modelId);
  }

  @Override
  public String getServiceIdStrByModelId(String modelId) {
    if (StringUtils.isBlank(modelId)) {
      return null;
    }

    StringBuilder sb = new StringBuilder();

    List<SkyService> services = this.searchServiceByModelId(modelId);
    if (services != null && services.size() > 0) {
      for (SkyService service : services) {
        sb.append("{").append(service.getId()).append("}");
      }
    }
    return sb.toString();
  }

  @Override
  public void saveProcessService(String modelId, String serviceId) {
    if (!StringUtils.isBlank(serviceId) && !StringUtils.isBlank(modelId)) {
      skyServiceDao.saveProcessService(modelId, serviceId);
    }
  }

  @Override
  public void deleteProcessService(String modelId, String serviceId) {
    if (!StringUtils.isBlank(serviceId) && !StringUtils.isBlank(modelId)) {
      skyServiceDao.deleteProcessService(modelId, serviceId);
    }
  }

}
